package dao

import (
	"encoding/json"
	"fmt"
	"gorm.io/gorm"
	"time"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/request"
	"yundian/internel/app/models/roles"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
)

// -------------------- dao层 - 角色相关操作 -----------------------//

type RoleDao struct {
}

func NewRoleDao() *RoleDao {
	return &RoleDao{}
}

// GetRoleList 获取角色列表
func (d *RoleDao) GetRoleList(param *request.RoleListReq) *dingo.ErrorWrap {
	var (
		lst    []*roles.RoleWithPermission
		count  int64
		limit  int = param.PageSize
		offset int = param.PageSize * (param.PageNo - 1)
	)

	db := global.Orm.Table("roles")
	if param.Label != "" {
		db.Where("label like ? ", fmt.Sprint("%", param.Label, "%"))
	}
	if param.Name != "" {
		db.Where("name like ? ", fmt.Sprint("%", param.Name, "%"))
	}
	if param.Status > 0 {
		db.Where("status = ? ", param.Status)
	}

	db.Limit(limit).Offset(offset).Find(&lst).Offset(-1).Limit(-1).Count(&count)
	return dingo.ErrorIf(db.Error, lst, count)
}

// GetRoleList 获取角色列表
func (d *RoleDao) GetRoleListNoPager() *dingo.ErrorWrap {
	lst := make([]*roles.RolesModel, 0)
	db := global.Orm.Table("roles").Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *RoleDao) GetStaffRoleList() *dingo.ErrorWrap {
	lst := make([]*roles.RolesModel, 0)
	db := global.Orm.Table("roles").Where("is_admin = ?", 4).Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

func (d *RoleDao) GetRoleListByIsAdmin(isAdmin int) *dingo.ErrorWrap {
	lst := make([]*roles.RolesModel, 0)
	db := global.Orm.Table("roles")

	if isAdmin != helper.TypeNumIsAdminOperator {
		db.Where("is_admin = ?", isAdmin)
	}
	db.Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

// 获取对应角色下的权限列表
func (d *RoleDao) GetRolesByIsAdmin(isAdmin int) *dingo.ErrorWrap {
	lst := make([]*roles.RolesModel, 0)
	db := global.Orm.Debug().Table("roles").Where("is_admin = ?", isAdmin).Where("status = 1").Find(&lst)
	return dingo.ErrorIf(db.Error, lst)
}

// GetRoleInfoFromId 获取角色详情
func (d *RoleDao) GetRoleInfoFromId(roleId int) *dingo.ErrorWrap {
	m := &roles.RoleWithLogin{}
	db := global.Orm.Table("roles").Where("id = ?", roleId).Find(m)
	return dingo.ErrorIf(db.Error, m)
}

func (d *RoleDao) GetRoleNameById(roleId int) *dingo.ErrorWrap {
	m := &roles.RolesModel{}
	sql := "select name from roles where id = ? limit 1"
	db := global.Orm.Raw(sql, roleId).Find(&m)
	return dingo.ErrorIf(db.Error, m)
}

// InsertRole 新增角色
func (d *RoleDao) InsertRole(param *request.RoleInsertReq) *dingo.ErrorWrap {
	m := roles.New()
	m.Describe = param.Describe
	m.Status = param.Status
	m.Label = param.Label
	m.Name = param.Name
	m.IsAdmin = param.IsAdmin
	m.CreateAt = dingo.Time(time.Now().Unix())
	m.UpdateAt = dingo.Time(time.Now().Unix())
	db := global.Orm.Table("roles").
		Select("label", "name", "is_admin", "status", "describe", "create_at", "update_at").
		Create(m)
	return dingo.ErrorIf(db.Error, m)
}

// InsertRolePermission 新增角色权限关联表
func (d *RoleDao) InsertRolePermission(m map[string]interface{}) *dingo.ErrorWrap {
	db := global.Orm.Table("role_permission").Create(m)
	return dingo.ErrorIf(db.Error, true)
}

// UpdateRole 更新角色
func (d *RoleDao) UpdateRole(param *request.RoleInsertReq) *dingo.ErrorWrap {
	err := global.Orm.Transaction(func(tx *gorm.DB) error {
		// 1. 修改角色表
		tx = tx.Table("roles").Where("id = ?", param.Id).
			Updates(roles.RolesModel{
				Label:    param.Label,
				Name:     param.Name,
				IsAdmin:  param.IsAdmin,
				Describe: param.Describe,
				UpdateAt: dingo.Time(time.Now().Unix()),
				Status:   param.Status})
		if err := tx.Error; err != nil {
			// 返回任何错误都会回滚事务
			return err
		}
		// 2. 删除角色路由关联表
		for _, p := range param.Permissions {
			tx.Exec("delete from role_permission where role_id = ? and permission_id = ?", param.Id, p.Id)
			if err := tx.Error; err != nil {
				return err
			}
		}

		// 3. 新增角色路由关联表
		for _, p := range param.Permissions {
			if len(p.ActionList) > 0 {
				actList, _ := json.Marshal(p.ActionList)
				// 新增入库 - 角色权限关联表
				insertMap := map[string]interface{}{
					"role_id":       param.Id,
					"permission_id": p.Id,
					"action_list":   string(actList),
				}
				tx.Table("role_permission").Create(insertMap)
				if err := tx.Error; err != nil {
					return err
				}
			}
		}
		// 返回 nil 提交事务
		return nil
	})

	return dingo.ErrorIf(err, true)
}

// UpdateRoleStatus 更新状态
func (d *RoleDao) UpdateRoleStatus(id int, status int8) *dingo.ErrorWrap {
	sql := "update roles set status = ? where id = ?"
	db := global.Orm.Exec(sql, status, id)
	return dingo.ErrorIf(db.Error, true)
}

// DeleteRole 删除角色
func (d *RoleDao) DeleteRole(id int) *dingo.ErrorWrap {
	err := global.Orm.Transaction(func(tx *gorm.DB) error {
		// 1. 删除权限表
		tx = tx.Exec("delete from roles where id = ?", id)
		if err := tx.Error; err != nil {
			return err
		}
		// 2. 删除角色路由关联表
		tx.Exec("delete from role_permission where role_id = ?", id)
		if err := tx.Error; err != nil {
			return err
		}
		// 返回 nil 提交事务
		return nil
	})
	return dingo.ErrorIf(err, true)
}
